<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/spark-md5/2.0.2/spark-md5.min.js"></script>
</head>

<body>
    <input type="file" id="file" />
    <button onclick="upload()">上传</button>
    <script>

        const chunkSize = 1 * 1024 * 1024// 1M 一个切片
        function getHash(file) {
            return new Promise((resolve,reject)=>{
                // 2.计算分片信息
                const fileSize = file.size // 文件大小
                const chunkCount = Math.ceil(fileSize / chunkSize) // 总分片数
                let chunkNumber = 0  // 分片编号
                // 3.获取分片
                const render = new FileReader()
                const spark = new SparkMD5.ArrayBuffer()
                render.onload = function (e) {  // render.readAsArrayBuffer 会触发 onload
                    spark.append(e.target.result)
                    chunkNumber++
                    if (chunkNumber < chunkCount) {
                        loadNext()
                    } else {
                        const sparkMd5 = new SparkMD5()
                        sparkMd5.append(spark.end())
                        sparkMd5.append(file.name)
                        const hexHash = sparkMd5.end()
                        resolve(hexHash)
                        console.log('结束 hash 运算')
                    }
                }
                const loadNext = () => {
                    const start = chunkNumber * chunkSize
                    const end = start + chunkSize > fileSize ? fileSize : start + chunkSize // 防止越界
                    render.readAsArrayBuffer(file.slice(start, end))
                }
                loadNext()
            })
        }
        async function upload() {
            const file = document.getElementById('file').files[0]
            if (!file) {
                return
            }
            // 1.计算分片信息
            const fileSize = file.size // 文件大小
            const chunkCount = Math.ceil(fileSize / chunkSize) // 总分片数
            const hash = await getHash(file)
            debugger
            // 2.构建并发送请求
            const axiosArrs = []
            for (let chunkNumber = 0; chunkNumber < chunkCount; chunkNumber++) {
                const start = chunkNumber * chunkSize
                const end = Math.min(fileSize, start + chunkSize)
                const formData = new FormData()
                formData.append('file', file.slice(start, end))
                formData.append('total', chunkCount)
                formData.append('index', chunkNumber)
                formData.append('size', fileSize)
                formData.append('name', file.name)
                formData.append('currentSize', end - start)
                formData.append('hash',hash)
                const axiosOptions = {
                    onUploadProgress(e) {
                        console.log(chunkNumber, chunkCount)
                    }
                }
                axiosArrs.push(axios.post('/upload', formData, axiosOptions))
            }
            await axios.all(axiosArrs)
        }
    </script>
</body>

</html>